package Server.Agent;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import Server.Model.Base.SHMUser;
import Server.Model.Hall.ApiHandle;
import Server.Model.Hall.dthall;
import admin.AdminRedis;
import common.routine.GlobalSetting;
import common.routine.JsonUtils;
import common.routine.NodeInfoVo;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import logic.iface.LogicServer;
import msg.protocal.ActorEntry;
import msg.protocal.CMD_enum;
import msg.protocal.ClientPeerMsg;
import msg.protocal.ObjectWrapper;
import net.sf.json.JSONObject;
import network.handler.HandlerWrapperMgr;
import network.handler.NetHandlerMgr;
import network.handler.NetworkSender;
import network.handler.NodePeerMgr;
import network.handler.ProtocolMsg;

public class GameAgent {
	public ChannelHandlerContext mCtx;
	public String _uid;
	public GameAgent() {
		CID = __id++;
		agents.put(CID, this);	
		m_heartTime = System.currentTimeMillis();
		/*
		try
		{
			KickDeadSessions();
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		*/
	}
	public GameAgent(SHMUser _user){
		user = _user;
	}
	public ChannelHandlerContext getAgentChannelHandlerContext(){
		return mCtx;
	}
	public void printTrack(int num){  
	    StackTraceElement[] st = Thread.currentThread().getStackTrace();  
	    if(st==null){  
	        System.out.println("无堆栈...");  
	        return;  
	    }  
	    StringBuffer sbf =new StringBuffer();  
	    for(StackTraceElement e:st){  
	        if(sbf.length()>0){  
	            sbf.append(" <- ");  
	            sbf.append(System.getProperty("line.separator=========" + num));  
	        }  
	        sbf.append(java.text.MessageFormat.format("{0}.{1}() {2}"  
	                ,e.getClassName()  
	                ,e.getMethodName()  
	                ,e.getLineNumber()));  
	    }  
	    System.out.println(sbf.toString());  
	}  
	public void onUserRegistered(String uid,ChannelHandlerContext ctx) {
		CurConnection++;
		if(MaxConnection < CurConnection)
		{
			MaxConnection = CurConnection;
		}
		_uid = uid;
		mCtx = ctx;
		onClientConnect();
	}	
	public static long prevUserUnregisteredTime = 0;
	public static int userSerialDisconnectCount = 0;
	public void onUserUnregistered(ChannelHandlerContext ctx){
		if(prevUserUnregisteredTime == 0){
			prevUserUnregisteredTime = System.currentTimeMillis();
		}else{
			long curr = System.currentTimeMillis();
			if((curr - prevUserUnregisteredTime) < 200){
				userSerialDisconnectCount++;
				prevUserUnregisteredTime = curr;
				if(userSerialDisconnectCount >= 60){
					System.out.println("频繁掉线情况发生");
					printTrack(CID);
					userSerialDisconnectCount = 0;
					//准备重启
//					if(GlobalSetting.getInstance().canSelfServerWorking()){
//						GlobalSetting.getInstance().setSelfServerCanWorking(false);
//						System.out.println("准备重启");
//						//通知所有gate
//						net.sf.json.JSONObject pub = new net.sf.json.JSONObject();
//						pub.put("command","pub_request_logic_reboot");
//						pub.put("value1","" + NodeInfoVo.getKey(GlobalSetting.getInstance().getSelfNodeInfo()));
//						AdminRedis.getInstance().pubAdminSubMsg(pub);
//						
//						
//						//LogicServer.getInstance().startShutDown();
//						ProtocolMsg sendmsg = NetworkSender.genProtocolMsg(CMD_enum.LOGIC_GET_DOWN,"","");
//						
//						ObjectWrapper newwrapper = new ObjectWrapper();
//						newwrapper._obj = sendmsg;
//						newwrapper._actorEntry = new ActorEntry("","","");
//						NetHandlerMgr.getInstance().pushMsgNoNotify(newwrapper);
//					}
				}
			}else{
				userSerialDisconnectCount = 0;
				prevUserUnregisteredTime = curr;
			}
		}
		CurConnection--;
		
		if(CurConnection < 0)
		{
			System.out.println("OH");
		}
		int cntAgent = agents.size();
		System.out.printf("%d OnDisconnect :\t Connection: %d | %d_%d\n",MaxConnection,CurConnection,CID,cntAgent);
		
		onClientClose();
	}

	public static Map<Integer,GameAgent> agents = new HashMap<Integer,GameAgent>();
	public static int __id = 1;
	public static int MaxConnection = 0;
	public static int CurConnection = 0;
	
	public Long m_heartTime;
	
	public int CID = 0;	
	public SHMUser user;	
	public SHMUser getUser() {
		return user;
	}
	public Integer getCID()
	{
		return CID;
	}	
	public Integer getUID()
	{
		if(user != null)
		{
			return user.getUid();
		}
		return 0;
	}
	public static void setUser(Integer _Uid, SHMUser shmUser) {
		GameAgent agent = agents.get(_Uid);
		if (agent!=null) {
			agent.setUser(shmUser);
		}
	}
	public void setUser(SHMUser user) {
		this.user = user;
	}
    public  String Hand(String url){
    	return ApiHandle.Hand(this,url,null);
    }
    public void add_client(GameAgent agent){  
    	agents.put(agent.CID, agent);	
    }  

    public static void del_client(GameAgent agent){  
    	if(true){
    		//added by zws
    		int cid = agent.CID;
    		int uid = 0;
    		if(agent.user != null){
    			uid = agent.user.m_lUid;
    		}
    		if(agents.containsKey(cid)){
    			agents.remove(cid);
    		}
    		if(uid != 0){
    			dthall.getInstance().delUser(uid);
    		}
    		return;
    	}
		Iterator<Map.Entry<Integer, GameAgent>> iterAgent = agents.entrySet().iterator();  
        while(iterAgent.hasNext()){  
            Map.Entry<Integer, GameAgent> entry=iterAgent.next();  
            GameAgent value=entry.getValue();  
            if(value == agent){  
            	iterAgent.remove();        //OK   
            }  
        }  
    }
    public static GameAgent find_client(int in_CID)
    {
    	if(agents.containsKey(in_CID) )
    	{
    		return agents.get(in_CID);
    	}
    	return null;
    }

    public static GameAgent findAgentByUid(int uid){
		Iterator<Map.Entry<Integer, GameAgent>> iterAgent = agents.entrySet().iterator();  
        while(iterAgent.hasNext()){  
            Map.Entry<Integer, GameAgent> entry=iterAgent.next();  
            GameAgent value=entry.getValue();  
            if(value.user != null && value.user.getUid() == uid){  
            	return value;
            }  
        }  
        return null;
    }
	public void Disconnect()
	{
		if(mCtx != null)
		{
			mCtx.disconnect();
			mCtx = null;
		}
	}
	public void CloseChannel(){
		if(mCtx != null){
			mCtx.channel().close();
		}
	}
	public static void Send(int CID,String msg){
		GameAgent agent = agents.get(CID);
		if (agent != null && agent.mCtx != null) {
			LogicServer.sendClientMsg(msg,LogicServer.getUserAccount(agent),agent.mCtx);
		}else{
			System.out.println("can not find agent:" + msg);
		}
	}
	public static void Broadcast(String msg){
		try
		{
			Iterator<Map.Entry<Integer, GameAgent>> it = agents.entrySet().iterator();
	        while(it.hasNext()){  
	            Map.Entry<Integer, GameAgent> entry=it.next();  
	            GameAgent agent=entry.getValue();  
	            if(agent != null){
	            	agent.SendMessage(msg);
	            }  
	        }
		}catch(Exception e)
		{
			e.printStackTrace();
		}	
	}

	public void onClientConnect() {
		add_client(this);
		try {
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void onClientClose() {		
		del_client(this);

		dthall.getInstance().OnClientClose(this);
		m_heartTime = System.currentTimeMillis();
		
	}

	public int getUid() {
		if (user != null) {
			return user.m_lUid;
		}
		return 0;
	}
	public boolean m_bRemove = false;
	public void Remove()
	{
		m_bRemove = true;
	}	
	public boolean ShouldBeRemoved()
	{
		return m_bRemove;
	}
	public boolean isTimeOut()
	{
		if(m_heartTime > 0 && System.currentTimeMillis() - m_heartTime > 3600*1000)
		{
			return true;
		}
		return false;
	}	

	public static synchronized void KickDeadSessions()
	{
		try
		{
			Iterator<Map.Entry<Integer, GameAgent>> it = agents.entrySet().iterator();
	        while(it.hasNext()){  
	            Map.Entry<Integer, GameAgent> entry=it.next();  
	            int key=entry.getKey();
	            GameAgent value=entry.getValue();  
	            if(value != null && (value.ShouldBeRemoved() || value.isTimeOut())){
	                System.out.println("remove dead agent cid: "+key);  
	                value.Disconnect();
	                it.remove();        //OK
	            }  
	        }
		}catch(Exception e)
		{
			
		}	
	}   
	public void SendMessage(String message) {
		if(mCtx != null && user != null && !user.isAndroidPlayer()){
			LogicServer.sendClientMsg(message,LogicServer.getUserAccount(this),mCtx);
		}else{
			System.out.println("can not find agent:" + message);
		}
	}
    public String ip = null;
    public String getIP(){
    	if (ip != null) {
			return ip;
		}
    	if (mCtx == null) {
			return null;
		}
    	ip = mCtx.channel().remoteAddress().toString();
    	ip = ip.split("\\:")[0];
    	this.ip = ip.substring(1);
    	return this.ip;
    }
	public static void DiaoXianAll() {
		try
		{
			Iterator<Map.Entry<Integer, GameAgent>> it = agents.entrySet().iterator();
	        while(it.hasNext()){  
	            Map.Entry<Integer, GameAgent> entry=it.next();  
	            GameAgent value=entry.getValue();  
	            if(value != null){
	                value.Disconnect();
	                it.remove();        //OK
	            }  
	        }
		}catch(Exception e)
		{
			
		}	
	}
}